package com.zzh.compilation.semantic;

import com.zzh.compilation.model.Token;
import com.zzh.compilation.syntax.SyntaxAnalyzer;

import java.util.ArrayList;
import java.util.List;

public class SemanticAnalyzer {
    private static List<Token> tokens;
    private static int position = 0;
    private static boolean hasError = false;
    private static StringBuilder errorMessage = new StringBuilder();
    private static List<Quadruple> quadruples = new ArrayList<>();
    private static int tempCount = 0;


    public static List<Quadruple> analyze(List<Token> inputTokens) {
        tokens = inputTokens;
        if (program()) {
            System.out.println("Semantic analysis success.");
        } else {
            System.out.println("Semantic analysis failed.");
        }
        return quadruples;
    }

    private static boolean program() {
        if (matchTokenType(1)) {//begin
            if (!statementList()) return false;//检查中间语句
            if (!matchTokenType(6)) {//end
                recordError("Missing 'end' keyword");
                return false;
            }
            if (!matchTokenType(28)) {
                recordError("Missing end symbol '#'");
                return false;
            }
        } else {
            recordError("Missing 'begin' keyword at the start");
            return false;
        }
        return true;
    }

    private static boolean statementList() {
        if (!statement()) return false;
        while (matchTokenType(25)) {
            if (!statement()) return false;
        }
        return true;
    }

    private static boolean statement() {
        return assignmentStatement();
    }

    private static boolean assignmentStatement() {
        String varName = null;
        if (matchTokenType(10)) {
            varName = tokens.get(position - 1).getValue();
            if (matchTokenType(18)) {
                String expResult = expression();
                if (expResult!= null) {
                    quadruples.add(new Quadruple(":=", expResult, null, varName));
                    return true;
                }
            } else {
                recordError("Missing ':=' after variable name");
                return false;
            }
        }else if ("end".equals(tokens.get(position).getValue())){
            return true;// 避免每次到这里检查end就爆错
        }else {
            recordError("Missing variable name for assignment statement");
            return false;
        }
        return false;
    }

    private static String expression() {
        String termResult1 = term();
        if (termResult1 == null) return null;
        while (matchTokenType(30) || matchTokenType(31)) {
            String op = tokens.get(position - 1).getValue();
            String termResult2 = term();
            if (termResult2 == null) return null;
            String temp = "T" + (++tempCount);
            quadruples.add(new Quadruple(op, termResult1, termResult2, temp));
            termResult1 = temp;
        }
        return termResult1;
    }

    private static String term() {
        String factorResult1 = factor();
        if (factorResult1 == null) return null;
        while (matchTokenType(32) || matchTokenType(33)) {
            String op = tokens.get(position - 1).getValue();
            String factorResult2 = factor();
            if (factorResult2 == null) return null;
            String temp = "T" + (++tempCount);
            quadruples.add(new Quadruple(op, factorResult1, factorResult2, temp));
            factorResult1 = temp;
        }
        return factorResult1;
    }

    private static String factor() {
        if (matchTokenType(10)) {
            return tokens.get(position - 1).getValue();
        } else if (matchTokenType(0)) {
            return tokens.get(position - 1).getValue();
        } else if (matchTokenType(34)) {
            String expResult = expression();
            if (expResult!= null && matchTokenType(35)) {
                return expResult;
            } else {
                recordError("Missing closing parenthesis ')'");
                return null;
            }
        }
        recordError("Expected variable, number or '(' for factor");
        return null;
    }


    // 根据token存放的类型判断是否匹配
    private static boolean matchTokenType(int expectedType) {
        if (position < tokens.size() && tokens.get(position).getType() == expectedType) {
            position++;
            return true;
        }
        return false;
    }

    private static void recordError(String message) {
        if (!hasError && position < tokens.size()) {
            Token currentToken = tokens.get(position);
            errorMessage.append("Line ").append(currentToken.getLineNumber()).append(": ").append(message).append('\n');
            hasError = true;
        }
    }
}